#ifndef FRAME_INCLUDED
#define FRAME_INCLUDED

#include <boost/lexical_cast.hpp>
#include "pcap++/PcapOffline.h"
#include "pcap++/config.h"
#include <pcap++/Packet.h>
#include <pcap++/DataLink.h>

#include "header.h"


typedef uint64_t FlowID;

uint64_t flowID(const struct sniff_ip* ip, const struct sniff_tcp *tcp);

class CharArray
{
public:
	CharArray(const char *payload, const u_int payload_len)
		: 	m_payload(payload),
		    m_payload_len(payload_len)
	{
	}
	const char * getData()
	{
		return m_payload;
	}
	const u_int getLen()
	{
		return m_payload_len;
	}
private:
	const char *m_payload;
	const u_int m_payload_len;
};

//get_capture_length
class Frame
{
public:
	Frame(pcappp::Packet const& packet)
	{
		tcp = NULL;
		ip = (struct sniff_ip*)(packet.get_data() + SIZE_ETHERNET);
		u_int size_ip;
		size_ip = IP_HL(ip)*4;
		if (size_ip < 20)
		{
			//        printf("   * Invalid IP header length: %u bytes\n", size_ip);
			ip = NULL;
			return;
		}

		if( IPprotocol() == TCP_PROTOCOL )
		{
			u_int size_tcp;
			tcp = (struct sniff_tcp*)(packet.get_data() + SIZE_ETHERNET + size_ip);

			size_tcp = TH_OFF(tcp)*4;

			if (size_tcp < 20) {
				//              printf("   * Invalid TCP header length: %u bytes\n", size_tcp);
				tcp = NULL;
				return;
			}
			payload = (char*)(packet.get_data() + SIZE_ETHERNET + size_ip + size_tcp);
			payload_len = ntohs(ip->ip_len) - (size_ip + size_tcp);


		}
	}
	bool isOK()
	{
		if(ip && (tcp))
			return true;
		return false;
	}
	FlowID getFlowID()
	{
		return flowID(ip,tcp);
	}

	std::string getPayload(uint32_t len = 0) const
	{
		if(len == 0)
			return std::string(payload, payload_len);
		else
		{
			if(payload_len <= len)
				return std::string(payload, payload_len);
			else
				return std::string(payload, len);
		}
	}
	const char* getCharPayload() const
	{
		return payload;
	}
	const u_int getCharPayloadLen() const
	{
		return payload_len;
	}
	/*
	CharArray getFullFrame()
	{
		return CharArray(payload, payload_len);

	}*/
	CharArray getPayloadChar()
	{
		return CharArray(payload, payload_len);
	}
	u_char IPprotocol()
	{
		if(ip)
			return  ip->ip_p;
		return 255;
	}
	struct sniff_ip* getIP() const
	{
		return ip;
	}
	struct sniff_tcp* getTCP() const
	{
		return tcp;
	}
	struct sniff_ip *ip;
	struct sniff_tcp *tcp;
	char *payload;
	u_int payload_len;
};

#endif

